package cn.leida.ruoyi.system.dao.custom.impl;


import cn.hutool.core.util.NumberUtil;
import cn.leida.common.json.util.JsonCopyUtil;
import cn.leida.ruoyi.common.core.domain.entity.SysRole;
import cn.leida.ruoyi.system.dao.custom.SysMenuDaoCustom;
import com.alibaba.fastjson2.JSONObject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.query.sql.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

import java.util.ArrayList;
import java.util.List;

/**
 * 菜单表 复杂查询
 *
 * @author liutietou
 * @since 1.0  2020-12-11
 */
public class SysMenuDaoCustomImpl implements SysMenuDaoCustom {

    @PersistenceContext
    private EntityManager entityManager;


    @Override
    public Page<SysRole> findMixPage(SysRole req, Pageable pageable) {
        ArrayList<Object> params = new ArrayList<>();
        StringBuilder sql = new StringBuilder();
        buildFrom(sql);
        buildWhere(sql, req, params);
        Query totalQuery = entityManager.createNativeQuery("select count(*)   " + sql.toString() + " ");
        int size = params.size();
        for (int i = 0; i < size; i++) {
            totalQuery.setParameter(i + 1, params.get(i));
        }

        List<?> resultList = totalQuery.getResultList();
        if (resultList.isEmpty()) {
            return Page.empty();
        }
        String totalStr = resultList.get(0) + "";
        long total = 0;
        if (NumberUtil.isLong(totalStr)) {
            total = NumberUtil.parseLong(totalStr);
        }

        Query contentQuery = entityManager.createNativeQuery(buildSelect() + sql.toString() + buildOrder());
        for (int i = 0; i < size; i++) {
            contentQuery.setParameter(i + 1, params.get(i));
        }
        contentQuery.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        contentQuery.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
        contentQuery.setMaxResults(pageable.getPageSize());
        List<Object> results = contentQuery.getResultList();
        List<SysRole> collect = new ArrayList<>();
        //  map 转对象
        for (Object obj : results) {
            JSONObject dataJson = JsonCopyUtil.javaFieldJson(SysRole.class, JSONObject.from(obj));
            SysRole sysUser = dataJson.toJavaObject(SysRole.class);
            collect.add(sysUser);
        }
        return new PageImpl<>(collect, pageable, total);
    }


    private String buildSelect() {
        StringBuffer sql = new StringBuffer();
        sql.append(" select distinct r.role_id roleId, r.role_name roleName, r.role_key roleKey, r.role_sort roleSort, r.data_scope dataScope ");
        sql.append(" , r.menu_check_strictly menuCheckStrictly, r.dept_check_strictly deptCheckStrictly, r.status status, r.del_flag delFlag ");
        sql.append(" , r.create_by createBy,r.create_time createTime ,r.update_by updateBy,r.update_time updateTime,r.remark remark ");
        return sql.toString();
    }

    private void buildFrom(StringBuilder sql) {
        sql.append(" from sys_role r  ");
        sql.append(" left join sys_user_role ur on ur.role_id = r.role_id  ");
        sql.append(" left join sys_user u on u.user_id = ur.user_id  ");
        sql.append(" left join sys_dept d on u.dept_id = d.dept_id  ");
    }

    private void buildWhere(StringBuilder sql, SysRole req, List<Object> params) {
        sql.append("  where r.del_flag = '0'  ");
        if (StringUtils.isNotBlank(req.getRoleName())) {
            sql.append("   AND r.role_name like ? ");
            params.add("%" + req.getRoleName() + "%");
        }
        if (StringUtils.isNotBlank(req.getStatus())) {
            sql.append("   AND r.status = ? ");
            params.add(req.getStatus());
        }
        if (StringUtils.isNotBlank(req.getRoleKey())) {
            sql.append("   AND r.role_key like ? ");
            params.add("%" + req.getRoleKey() + "%");
        }
        if (null != req.getParams().get("beginTime")) {
            sql.append("   AND date_format(r.create_time,'%y%m%d') >= date_format(?,'%y%m%d') ");
            params.add(req.getParams().get("beginTime"));
        }
        if (null != req.getParams().get("endTime")) {
            sql.append("   AND date_format(r.create_time,'%y%m%d') <= date_format(?,'%y%m%d') ");
            params.add(req.getParams().get("endTime"));
        }
        sql.append(req.getParams().getOrDefault("dataScope", ""));
    }

    private String buildOrder() {
        return " order by r.role_sort ";
    }


}
